// -----------------------------------------------------------------------
// <copyright file="Logger.cs" company="Microsoft">
// Logger for logging actions
// </copyright>
// -----------------------------------------------------------------------
namespace WebServer.BusinessLogic.Logs
{
    using System;
    using System.Diagnostics;
    using System.Globalization;
    using System.IO;
    using System.Text;
    using WebServer.BusinessLogic.Helpers;

    /// <summary>
    /// Has to log data into the file
    /// </summary>
    public sealed class Logger : ILogger
    {
        /// <summary>
        /// for sinhronizing
        /// </summary>
        private static object syncRoot = new object();

        /// <summary>
        /// Logger instanse
        /// </summary>
        private static volatile Logger instance;

        /// <summary>
        /// Internal variable to store log file
        /// </summary>
        private string loggerPath;

        /// <summary>
        /// Time of last creation
        /// </summary>
        private DateTime lastCreatedDate;

        /// <summary>
        /// Clock field
        /// </summary>
        private IClock clock;
        
        /// <summary>
        /// Gets or sets Logger instanse
        /// </summary>
        public static Logger Instance
        {
            get
            {
                if (instance == null)
                {
                    // lock the thread
                    lock (syncRoot)
                    {
                        // when locked check if was not created again by another thread
                        if (instance == null)
                        {
                            // create new singleton instance
                            instance = new Logger { clock = new SystemClock() };
                            instance.lastCreatedDate = instance.Clock.Now;
                        }
                    }
                }

                return instance;
            }

            set
            {
                instance = value;
            }
        }

        /// <summary>
        /// Gets or sets Clock
        /// </summary>
        public IClock Clock
        {
            get { return this.clock; }
            set { this.clock = value; }
        }

        /// <summary>
        /// Gets path to the log file. Changes on the day change.
        /// </summary>
        public string PathToLogFile
        {
            get
            {
                if (this.lastCreatedDate.Day != this.Clock.Now.Day)
                {
                    // date changed, should recreate file also
                    this.loggerPath = null;
                }

                if (this.loggerPath == null)
                {
                    // get directory for the log files
                    string loggerDirectory = Configurator.Instance.LoggerPath;

                    // create directory if it doesn't exist
                    var dir = Directory.CreateDirectory(loggerDirectory);

                    if (dir.Exists)
                    {
                        this.loggerPath = loggerDirectory.TrimEnd(new[] { '\\' }) + "\\" +
                                      string.Format(CultureInfo.InvariantCulture, "{0}.txt", this.Clock.Now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
                    }
                }

                return this.loggerPath;
            }
        }

        /// <summary>
        /// Saves data into the file
        /// </summary>
        /// <param name="message">message string</param>
        /// <param name="useTrace">using Trace</param>
        public void Log(string message, bool useTrace = false)
        {
            // do not log when logging is not enabled
            if (!Configurator.Instance.EnableLogging)
            {
                return;
            }

            // prepare data
            string dataToWrite = string.Format(CultureInfo.InvariantCulture, "{0}\t{1}", DateTime.Now.ToString("HH:mm:ss"), message);
            
            // create necessary log file [lock inside if not found]
            this.CreateLogFileIfNeeded();

            // lock again
            lock (syncRoot)
            {
                File.AppendAllText(this.PathToLogFile, dataToWrite + "\r\n", Encoding.UTF8);
            }

            if (useTrace)
            {
                Trace.WriteLine(dataToWrite);
            }
        }

        /// <summary>
        /// Creates new file when it's not created yet
        /// </summary>
        private void CreateLogFileIfNeeded()
        {
            if (!File.Exists(this.PathToLogFile))
            {
                lock (syncRoot)
                {
                    var fs = File.Create(this.PathToLogFile);
                    fs.Close();
                }
            }
        }
    }
}